package com.sir.tao.carhire.shiro;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sir.tao.carhire.entity.table.AdministratorsEntity;
import com.sir.tao.carhire.entity.table.AdministratorsRoleRelationEntity;
import com.sir.tao.carhire.entity.table.RoleEntity;
import com.sir.tao.carhire.service.AdministratorsRoleRelationService;
import com.sir.tao.carhire.service.RoleService;
import com.sir.tao.carhire.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author dyy
 * @data 2021/12/6 17:08
 * @description:
 */
@Configuration
@Slf4j
public class MyRealm extends AuthorizingRealm {

    @Resource
    private RoleService roleService;
    @Resource
    private AdministratorsRoleRelationService administratorsRoleRelationService;

    @Lazy
    @Resource
    private RedisUtil redisUtil;

    @Override
    public void setName(String name){
        super.setName("myRealm");
    }
    @Override
    public boolean supports(AuthenticationToken token){
        return  token instanceof MyJsonWebToken;
    }


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        log.info("权限");
        //获取用户名和权限
        AdministratorsEntity administratorsEntity = (AdministratorsEntity) principals.getPrimaryPrincipal();
        String userName = administratorsEntity.getUsername();
        List<String> roleId = administratorsRoleRelationService
                .list(new LambdaQueryWrapper<AdministratorsRoleRelationEntity>()
                .inSql(AdministratorsRoleRelationEntity::getAdministratorsId,
                        "select id from administrators where username = '"+userName+"'"))
                .stream().map(AdministratorsRoleRelationEntity::getRoleId).collect(Collectors.toList());
        //第一次访问会从数据库查询角色,后面访问接口不会调用该方法
        List<RoleEntity> roles = roleService.list(new LambdaQueryWrapper<RoleEntity>()
                .in(RoleEntity::getId,roleId));
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> set = roles.stream().map(RoleEntity::getRoleName).collect(Collectors.toSet());
        info.addRoles(set);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        MyJsonWebToken myJsonWebToken = (MyJsonWebToken) authenticationToken;
        String token = (String) myJsonWebToken.getPrincipal();
        String userName = JwtUtil.getUserName(token);
        String userEntity = (String) redisUtil.get("prefix_user_entity_"+userName);
        AdministratorsEntity administratorsEntity = JSON.parseObject(userEntity,AdministratorsEntity.class);
        String trueToken = (String) redisUtil.get("prefix_user_token_"+userName);
        if(!token.equals(trueToken)){
            throw new AuthenticationException("token失效，请重新登录");
        }
        redisUtil.doRedis(administratorsEntity,token);
        return new SimpleAuthenticationInfo(administratorsEntity,token,getName());
    }
}
